pub mod config;
pub mod mcp;
pub mod routes;
pub mod state;
use anyhow::Result;
use state::AppState;
use tokio::sync::{Mutex, RwLock};
use tower_http::cors::{Any, CorsLayer};
// use libsql::{Builder, Value as LibValue};
// use libsql::{Connection, Database};
use rig_sqlite::{Column, ColumnValue, SqliteVectorStore, SqliteVectorStoreTable};
use rusqlite::ffi::sqlite3_auto_extension;
use sqlite_vec::sqlite3_vec_init;
use std::collections::HashMap;
use tracing_appender::rolling::{RollingFileAppender, Rotation};
// use std::env;
use rig::Embed;
use serde::Deserialize;
use std::sync::Arc;
use tokio_rusqlite::Connection;
use tracing::info;

#[derive(Embed, Clone, Debug, Deserialize)]
struct Document {
    id: String,
    #[embed]
    content: String,
}

impl SqliteVectorStoreTable for Document {
    fn name() -> &'static str {
        "documents"
    }

    fn schema() -> Vec<Column> {
        vec![
            Column::new("id", "TEXT PRIMARY KEY"),
            Column::new("content", "TEXT"),
        ]
    }

    fn id(&self) -> String {
        self.id.clone()
    }

    fn column_values(&self) -> Vec<(&'static str, Box<dyn ColumnValue>)> {
        vec![
            ("id", Box::new(self.id.clone())),
            ("content", Box::new(self.content.clone())),
        ]
    }
}

// 主函数
#[tokio::main]
async fn main() -> Result<()> {
    let file_appender = RollingFileAppender::new(
        Rotation::DAILY,
        "logs",
        format!("{}.log", env!("CARGO_CRATE_NAME")),
    );
    tracing_subscriber::fmt()
        .with_env_filter(
            tracing_subscriber::EnvFilter::from_default_env()
                .add_directive(tracing::Level::INFO.into()),
        )
        .with_writer(file_appender)
        .with_file(false)
        .with_ansi(false)
        .init();

    unsafe {
        sqlite3_auto_extension(Some(std::mem::transmute(sqlite3_vec_init as *const ())));
    }

    let conn = Connection::open("store.db").await?;

    // let url = std::env::var("TURSO_DATABASE_URL").expect("TURSO_DATABASE_URL must be set");
    // let token = std::env::var("TURSO_AUTH_TOKEN").expect("TURSO_AUTH_TOKEN must be set");

    // let db = Builder::new_remote_replica("database.sql", url, token)
    //     .build()
    //     .await
    //     .map_err(|e| anyhow::anyhow!("{}", e))?;
    //
    // let conn = db.connect().map_err(|e| anyhow::anyhow!("{}", e))?;

    let config = config::Config::retrieve("config.toml").await?;

    let mcp_manager = config.mcp.create_manager().await?;

    let fastembed_client = rig_fastembed::Client::new();

    let state = AppState {
        agents: Mutex::new(HashMap::new()),
        // db: RwLock::new(db),
        conn: RwLock::new(conn),
        mcp_manager: Arc::new(mcp_manager),
        fastembed: fastembed_client,
    };

    let cors = CorsLayer::new()
        .allow_origin(Any)
        .allow_methods(Any)
        .allow_headers(Any);

    let app = crate::routes::configure(state).layer(cors);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:6060").await?;
    info!("listening on {}", listener.local_addr()?);
    axum::serve(listener, app).await?;

    Ok(())
}
